package com.isesol.ime.service;

import com.github.pagehelper.*;
import com.google.common.collect.*;
import com.isesol.arch.common.service.*;
import com.isesol.arch.common.utils.*;
import com.isesol.arch.fluentvalidator.*;
import com.isesol.ime.dal.mapper.*;
import com.isesol.ime.dal.model.*;
import com.isesol.ime.dal.model.dto.*;
import com.isesol.ime.dto.*;
import com.isesol.ime.enums.*;
import com.isesol.ime.validator.message.*;
import lombok.extern.slf4j.*;
import org.apache.commons.collections.*;
import org.apache.commons.lang3.*;
import org.springframework.stereotype.*;

import javax.annotation.*;
import java.util.*;

/**
 * 报文管理
 *
 * @author peter zhang
 */
@Component
@Slf4j
public class MessageService extends BaseService {

	@Resource
	MessageMapper messageMapper;

	@Resource
	ParamMapper paramMapper;

	@Resource
	MsgParamsMapper msgParamsMapper;

	@Resource
	RuleTypeMapper ruleTypeMapper;

	@Resource
	SubscriptionMapper subscriptionMapper;

	@Resource
	CategoryMapper categoryMapper;

	@Resource
	ParamVersionMapper paramVersionMapper;

	/**
	 * 新增
	 *
	 * @param messageDTO
	 * @return
	 * @throws Exception
	 */
	public void create(MessageDTO messageDTO) throws Exception {

		FluentValidator.checkAll().failOver()
				.on(messageDTO, SpringContextHolder.getBean(MessageCreateValidator.class))
				.doValidate();

		MessageDO message;
		List<MessageDO> messageDOList = messageMapper.findByMsgIdAndStatus(messageDTO.getMsgId(), StatusEnum.OFF.getStatus());
		if (CollectionUtils.isNotEmpty(messageDOList) && messageDOList.size() == 1) {

			message = messageDOList.get(0);
			message.setMachineType(messageDTO.getMachineType());
			message.setMsgId(messageDTO.getMsgId());
			message.setMsgName(messageDTO.getMsgName());
			message.setMsgNumber(messageDTO.getMsgNumber());
			message.setRuleName(ruleTypeMapper.getById(Long.parseLong(messageDTO.getRuleType())).getName());
			message.setPreservation(messageDTO.isPreservation());
			message.setEncrypt(messageDTO.isEncrypt());
			message.setFeedback(messageDTO.isFeedback());
			message.setMemo(messageDTO.getMemo());
			message.setStatus(StatusEnum.ON.getStatus());
			message.setRule(messageDTO.getRule());
			message.setMachineType(messageDTO.getMachineType());
			message.setDefault(Boolean.valueOf(messageDTO.getIsDefault()));
			messageMapper.update(message);

		} else {

			message = new MessageDO();
			message.setMachineType(messageDTO.getMachineType());
			message.setMsgId(messageDTO.getMsgId());
			message.setMsgName(messageDTO.getMsgName());
			message.setMsgNumber(messageDTO.getMsgNumber());
			message.setRuleName(ruleTypeMapper.getById(Long.parseLong(messageDTO.getRuleType())).getName());
			message.setPreservation(messageDTO.isPreservation());
			message.setEncrypt(messageDTO.isEncrypt());
			message.setFeedback(messageDTO.isFeedback());
			message.setMemo(messageDTO.getMemo());
			message.setStatus(StatusEnum.ON.getStatus());
			message.setRule(messageDTO.getRule());
			message.setMachineType(messageDTO.getMachineType());
			message.setDefault(Boolean.valueOf(messageDTO.getIsDefault()));
			messageMapper.insert(message);

		}

		String paramIds = messageDTO.getParams();
		String[] paramIdArray = paramIds.split(",");

		modifyMsgParams(paramIdArray, message.getId());

	}

	public void modifyMsgParams(String[] paramIdArray, long mId) {

		Map<String, String> idsMap = Maps.newHashMap();
		for (String id : paramIdArray) {
			idsMap.put(id, id);
		}

		Map<String, MsgParamsDO> originAllMap = Maps.newHashMap();
		Map<String, MsgParamsDO> originEnableMap = Maps.newHashMap();
		Map<String, MsgParamsDO> originDisableMap = Maps.newHashMap();

		List<MsgParamsDO> modifyList = Lists.newArrayList();
		List<MsgParamsDO> insertList = Lists.newArrayList();

		List<MsgParamsDO> msgParamsDOList = msgParamsMapper.findByMsgId(String.valueOf(mId));
		if (!CollectionUtils.isEmpty(msgParamsDOList)) {
			for (MsgParamsDO msgParamsDO : msgParamsDOList) {
				long pId = msgParamsDO.getPId();
				if (msgParamsDO.getStatus().equals(StatusEnum.ON.getStatus())) {
					originEnableMap.put(String.valueOf(pId), msgParamsDO);
				}
				if (msgParamsDO.getStatus().equals(StatusEnum.OFF.getStatus())) {
					originDisableMap.put(String.valueOf(pId), msgParamsDO);
				}
				originAllMap.put(String.valueOf(pId), msgParamsDO);
			}

			for (String key : originAllMap.keySet()) {
				// 原来订阅了，现在不订阅了，置旧的status='0'
				if (!idsMap.containsKey(key)) {

					MsgParamsDO msgParamDO = originAllMap.get(key);

					if (msgParamDO.getStatus().equals(StatusEnum.ON.getStatus())) {

						msgParamDO.setStatus(StatusEnum.OFF.getStatus());
						modifyList.add(msgParamDO);
					}
				}
			}

			for (int i = 0; i < paramIdArray.length; i++) {

				String id = paramIdArray[i];

				if (!originAllMap.containsKey(id)) {

					MsgParamsDO msgParamDO = new MsgParamsDO();
					msgParamDO.setMsgId(mId);
					msgParamDO.setPId(Long.parseLong(id));
					msgParamDO.setStatus(StatusEnum.ON.getStatus());
					insertList.add(msgParamDO);

					continue;
				}
				modify(originEnableMap, id, modifyList, StatusEnum.ON.getStatus());
				modify(originDisableMap, id, modifyList, StatusEnum.ON.getStatus());
			}

		} else {

			for (int i = 0; i < paramIdArray.length; i++) {

				String id = paramIdArray[i];
				MsgParamsDO msgParamDO = new MsgParamsDO();
				msgParamDO.setMsgId(mId);
				msgParamDO.setPId(Long.parseLong(id));
				msgParamDO.setStatus(StatusEnum.ON.getStatus());
				insertList.add(msgParamDO);
			}
		}

		for (MsgParamsDO msgParamsDO : modifyList) {
			msgParamsMapper.update(msgParamsDO);

		}
		for (MsgParamsDO msgParamsDO : insertList) {
			msgParamsMapper.insert(msgParamsDO);
		}

	}

	public void modify(Map<String, MsgParamsDO> map, String id, List<MsgParamsDO> modifyList, String status) {

		MsgParamsDO msgParamsDO = map.get(id);

		if (msgParamsDO != null && !msgParamsDO.getStatus().equals(status)) {

			msgParamsDO.setStatus(status);
			modifyList.add(msgParamsDO);
		}
	}

	/**
	 * 删除报文,逻辑删除
	 *
	 * @param id
	 */
	public void del(String id) {

		MessageDTO messageDTO = new MessageDTO();
		messageDTO.setId(Long.valueOf(id));

		FluentValidator.checkAll().failOver()
				.on(messageDTO, SpringContextHolder.getBean(MessageDelValidator.class))
				.doValidate();

		MessageDO message = messageMapper.getById(Long.parseLong(id));
		message.setStatus(StatusEnum.OFF.getStatus());
		messageMapper.update(message);

		List<MsgParamsDO> msgParamsDOList = msgParamsMapper.findByMsgId(id);
		for (MsgParamsDO msgParamsDO : msgParamsDOList) {

			msgParamsDO.setStatus(StatusEnum.OFF.getStatus());
			msgParamsMapper.update(msgParamsDO);

		}

	}

	/**
	 * 报文修改
	 *
	 * @param messageDTO
	 * @return
	 * @throws Exception
	 */
	public void update(MessageDTO messageDTO) throws Exception {

		/**
		 * 参数校验
		 */
		FluentValidator.checkAll().failOver()
				.on(messageDTO, SpringContextHolder.getBean(MessageUpdateValidator.class))
				.doValidate();

		MessageDO message = messageMapper.getById(messageDTO.getId());
		message.setMsgId(messageDTO.getMsgId());
		message.setMsgName(messageDTO.getMsgName());
		message.setMsgNumber(messageDTO.getMsgNumber());
		message.setRuleName(ruleTypeMapper.getById(Long.parseLong(messageDTO.getRuleType())).getName());
		message.setRule(messageDTO.getRule());
		message.setPreservation(messageDTO.isPreservation());
		message.setEncrypt(messageDTO.isEncrypt());
		message.setFeedback(messageDTO.isFeedback());
		message.setMemo(messageDTO.getMemo());
		message.setDefault(Boolean.valueOf(messageDTO.getIsDefault()));

		if (StringUtils.isEmpty(messageDTO.getMachineType())) {

			message.setMachineType("i5");
		} else {

			message.setMachineType(messageDTO.getMachineType());
		}

		messageMapper.update(message);

		modifyMsgParams(messageDTO.getParams().split(","), messageDTO.getId());

	}

	/**
	 * 查找
	 *
	 * @param messageDTO
	 * @param page
	 * @param rows
	 * @return
	 */
	public PageInfo find(MessageDTO messageDTO, int page, int rows) {

		PageHelper.startPage(page, rows);

		String ruleName = null;

		if (!StringUtils.isEmpty(messageDTO.getRuleType())) {

			ruleName = ruleTypeMapper.getById(Long.parseLong(messageDTO.getRuleType())).getName();
		}

		List<MessageDTO> messageDOList = messageMapper.find(messageDTO.getMsgId(), messageDTO.getMsgName(),
				ruleName, messageDTO.getMachineType(), StatusEnum.ON.getStatus());

		return new PageInfo(messageDOList);

	}

	/**
	 * 可选参数
	 *
	 * @param messageParamsDTO
	 * @return
	 */
	public PageInfo findSelectableParams(MachineToolMessageParamsDTO messageParamsDTO, int page, int rows) {

		PageHelper.startPage(page, rows);

		List<ParamDTO> paramList = messageMapper.findSelectableParams(messageParamsDTO.getId(),
				messageParamsDTO.getParamVersion(),
				StatusEnum.ON.getStatus(),
				messageParamsDTO.getCategoryId(),
				messageParamsDTO.getParamId());

		return new PageInfo(paramList);

	}

	/**
	 * 已选参数
	 *
	 * @param id
	 * @return
	 */
	public List<ParamDTO> getSelectedParams(String id) {

		if (StringUtils.isBlank(id)) {
			return Lists.newArrayList();
		}

		List<ParamDTO> paramDTOList = msgParamsMapper.selectParamsForMessage(id);

		return paramDTOList;
	}

	/**
	 * 报文复制
	 *
	 * @param messageCopyDTO
	 */
	public void messageCopy(MessageDTO messageCopyDTO) {

		FluentValidator.checkAll().failOver()
				.on(messageCopyDTO, SpringContextHolder.getBean(MessageCopyValidator.class))
				.doValidate();

		MessageDO newMessage = new MessageDO();
		MessageDO message = messageMapper.getById(messageCopyDTO.getId());
		newMessage.setMsgId(messageCopyDTO.getMsgId());
		newMessage.setMsgName(messageCopyDTO.getMsgName());
		newMessage.setMsgNumber(message.getMsgNumber());
		newMessage.setRuleName(message.getRuleName());
		newMessage.setRule(message.getRule());
		newMessage.setFeedback(message.isFeedback());
		newMessage.setEncrypt(message.isEncrypt());
		newMessage.setPreservation(message.isPreservation());
		newMessage.setMemo(message.getMemo());
		newMessage.setStatus(message.getStatus());
		newMessage.setMachineType(message.getMachineType());
		newMessage.setDefault(message.isDefault());
		messageMapper.insert(newMessage);

		List<ParamDTO> ParamDTOList = msgParamsMapper.selectParamsForMessage(String.valueOf(message.getId()));

		for (int i = 0; i < ParamDTOList.size(); i++) {

			MsgParamsDO msgParamDO = new MsgParamsDO();
			msgParamDO.setPId(ParamDTOList.get(i).getId());
			msgParamDO.setMsgId(newMessage.getId());
			msgParamDO.setStatus(ParamDTOList.get(i).getStatus());
			msgParamsMapper.insert(msgParamDO);

		}
	}

	/**
	 * 根据id获得报文详情
	 *
	 * @param id
	 * @return
	 */
	public MessageDTO findById(String id) {

		return messageMapper.findById(id);

	}

	/**
	 * 订阅详情
	 *
	 * @param msgId
	 * @return
	 */
	public List<SubscriptionDO> getSubs(long msgId) {

		return subscriptionMapper.findByMsgIdAndStatus(msgId, StatusEnum.ON.getStatus());

	}

}
